package org.salatec.tapestry4e;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.core.resources.IProject;
import org.eclipse.jface.text.templates.ContextTypeRegistry;
import org.eclipse.jface.text.templates.persistence.TemplateStore;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.editors.text.templates.ContributionContextTypeRegistry;
import org.eclipse.ui.editors.text.templates.ContributionTemplateStore;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.salatec.tapestry4e.internal.TemplateContextTypeIdsForTML;
import org.salatec.tapestry4e.util.Logger;
import org.salatec.tapestry4e.util.T5ComponentsStore;

public class TMLPlugin extends AbstractUIPlugin {
	public final static String ID = "org.salatec.tapestry4e";

	private static TMLPlugin instance;

	/**
	 * The template store for the jsp editor.
	 */
	private TemplateStore fTemplateStore;

	private Map<String, T5ComponentsStore> storeMap;

	/**
	 * The template context type registry for the jsp editor.
	 */
	private ContextTypeRegistry fContextTypeRegistry;

	public TMLPlugin() {
		super();
		instance = this;
	}

	public static TMLPlugin getDefault() {
		return instance;
	}

	/**
	 * Returns the template store for the jsp editor templates.
	 * 
	 * @return the template store for the jsp editor templates
	 */
	public TemplateStore getTemplateStore() {
		if (fTemplateStore == null) {
			fTemplateStore = new ContributionTemplateStore(
					getTemplateContextRegistry(), getPreferenceStore(),
					"org.eclipse.wst.sse.ui.custom_templates");

			try {
				fTemplateStore.load();
			} catch (IOException e) {
				Logger.logException(e);
			}
		}
		return fTemplateStore;
	}

	/**
	 * Returns the template context type registry for the jsp plugin.
	 * 
	 * @return the template context type registry for the jsp plugin
	 */
	public ContextTypeRegistry getTemplateContextRegistry() {
		if (fContextTypeRegistry == null) {
			ContributionContextTypeRegistry registry = new ContributionContextTypeRegistry();
			registry.addContextType(TemplateContextTypeIdsForTML.ALL);
			registry.addContextType(TemplateContextTypeIdsForTML.NEW);
			registry.addContextType(TemplateContextTypeIdsForTML.TAG);
			registry.addContextType(TemplateContextTypeIdsForTML.ATTRIBUTE);
			registry
					.addContextType(TemplateContextTypeIdsForTML.ATTRIBUTE_VALUE);
			registry.addContextType(TemplateContextTypeIdsForTML.NEW_TAG);

			fContextTypeRegistry = registry;
		}

		return fContextTypeRegistry;
	}

	public IProject getProject() {
		IProject activeProject = null;
		ProjectWorker worker = new ProjectWorker(activeProject);
		PlatformUI.getWorkbench().getDisplay().syncExec(worker);
		activeProject = worker.getActiveProject();

		return activeProject;

	}

	/**
	 * Maintains a map of T5ComponentsStore by project. Returns the store that
	 * correspond to the given project.
	 * 
	 * @param project
	 * @return
	 */
	public T5ComponentsStore getStore(IProject project) {
		if (storeMap == null)
			storeMap = new HashMap<String, T5ComponentsStore>();
		if (storeMap.containsKey(project.getName())) {
			return storeMap.get(project.getName());
		} else {
			T5ComponentsStore store = new T5ComponentsStore(project);
			storeMap.put(project.getName(), store);
			return store;
		}
	}

	/**
	 * This thread works in the background to obtain the active project from the
	 * current selection.
	 * 
	 * @author Juan M. Salamanca
	 * 
	 *         11/03/2009
	 */
	private class ProjectWorker implements Runnable {

		private IProject activeProject;

		public ProjectWorker(IProject project) {
			super();
			this.activeProject = project;
		}

		public void run() {
			IWorkbenchWindow window = PlatformUI.getWorkbench()
					.getActiveWorkbenchWindow();
			if (window != null) {
				IWorkbenchPage page = window.getActivePage();
				if (page != null) {
					IEditorPart editor = page.getActiveEditor();
					if (editor != null) {
						IEditorInput input = editor.getEditorInput();
						if (input instanceof IFileEditorInput) {
							IFileEditorInput fileInput = (IFileEditorInput) input;
							activeProject = fileInput.getFile().getProject();
						}
					}
				}
			}
		}

		public IProject getActiveProject() {
			return activeProject;
		}

	}

}
